﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SettingsDefaultSerializer.cs" company="DevDigital">
//   DevDigital
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace Settings.NET.Serializers
{
    using System;

    /// <summary>
    /// Settings default serializer
    /// The default serializer uses XML serialization for reference types
    /// and string serialization for value types
    /// </summary>
    [Serializable]
    public class SettingsDefaultSerializer : ISettingsSerializer
    {
        /// <summary>
        /// The string serializer
        /// </summary>
        private readonly SettingsStringSerializer stringSerializer;

        /// <summary>
        /// The XML serializer
        /// </summary>
        private readonly SettingsXmlSerializer xmlSerializer;

        /// <summary>
        /// Initializes a new instance of the <see cref="SettingsDefaultSerializer" /> class.
        /// </summary>
        public SettingsDefaultSerializer()
        {
            this.stringSerializer = new SettingsStringSerializer();
            this.xmlSerializer = new SettingsXmlSerializer();
        }

        /// <summary>
        /// Serializes the specified value.
        /// </summary>
        /// <typeparam name="TValue">The type of the value.</typeparam>
        /// <param name="value">The value.</param>
        /// <returns>The serialized value</returns>
        public string Serialize<TValue>(TValue value)
        {
            if (ConversionHelper.IsNull(value))
            {
                return null;
            }

            var isSimpleType = IsSimpleType<TValue>();
            return isSimpleType
                ? this.stringSerializer.Serialize(value) 
                : this.xmlSerializer.Serialize(value);
        }

        /// <summary>
        /// Deserializes the specified value.
        /// </summary>
        /// <typeparam name="TValue">The type of the value.</typeparam>
        /// <param name="value">The value.</param>
        /// <returns>The deserialized value</returns>
        public TValue Deserialize<TValue>(string value)
        {
            if (ConversionHelper.IsNull(value))
            {
                return default(TValue);
            }

            var isSimpleType = IsSimpleType<TValue>();
            return isSimpleType
                ? this.stringSerializer.Deserialize<TValue>(value)
                : this.xmlSerializer.Deserialize<TValue>(value);
        }

        /// <summary>
        /// Determines whether the type is a simple type.
        /// The following are considered simple types:
        ///      A string
        ///      Any predefined value type
        ///      A nullable type
        ///      An enum
        ///      A TimeSpan
        /// </summary>
        /// <typeparam name="T">The type</typeparam>
        /// <returns>
        ///   <c>true</c> if the type is a simple type; otherwise, <c>false</c>.
        /// </returns>
        private static bool IsSimpleType<T>()
        {

            var isSimpleType =
                ConversionHelper.IsString<T>() ||
                ConversionHelper.IsPredefinedValueType<T>() ||
                ConversionHelper.IsNullableType<T>() ||
                typeof(T).IsEnum ||
                typeof(T) == typeof(TimeSpan);

            return isSimpleType;
        }
    }
}